<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>35、高阶函数_函数柯里化</title>
</head>
<body>
  <div id="test"></div>

  <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
  <script src="https://cdn.staticfile.org/prop-types/15.6.1/prop-types.js"></script>

  <script type="text/babel">
    class Demo extends React.Component {
      state = {
        username: '',
        password: ''
      }
      handleSubmit = (event) => {
        event.preventDefault()
        alert(`用户名：${this.state.username}，密码：${this.state.password}`)
      }
      saveUsername = (event) => {
        this.setState({ username: event.target.value })
      }
      savePaasword = (event) => {
        this.setState({ paasword: event.target.value })
      }
      // #region
      /*
        高阶函数：如果一个函数符合下面2个规范中的任何一个，那该函数就是高阶函数
          1. 若A函数，接受的参数是一个函数，那么A就可以称之为高阶函数
          2. 若A函数，调用的返回值依然是一个函数，那么A就可以称之为高阶函数
          常见的高阶函数有：
            Promise  new Promise((resolve, reject) => {})
            setTimeout  setTimeout(() => {}, 2000)
            数组身上的一些方法  例如：arr.map()
        
        函数的柯里化：通过函数调用继续返回函数的方式，实现多次接收参数最后统一处理的函数编码形式
       */
      // #endregion

      //  saveFormData方法就是函数柯里化的写法：通过saveFormData函数调用继续返回的函数，接受的参数最后统一处理
      saveFormData = (dataType) => {
        return (event) => {
          console.log(dataType,event.target.value)
          // 将输入标签的值存到state中
          this.setState({
            /*
              此处的dataType外面为何要包一层[]？
              let a = 'name'
              let obj = {}
              // 如果想实现这种数据格式：
              obj: {
                name: 'tom'
              }
              // 就要这样写
              obj[a] = 'tom'
            */
            [dataType]: event.target.value
          })
        }
      }
      render() {
        return (
          <form onSubmit={ this.handleSubmit }>
            {/* 可输入的表单标签，如果想实现vue那样的双向绑定：数据修改页面实时更新，就需要使用onChange事件和setState去改变数据的状态
            但是如果可输入的表单标签很多，每个标签都要写个onChange事件，就很麻烦，代码也很冗余 */}
            {/* 用户名：<input type="text" name="username" onChange={ this.saveUsername } />
            密码：<input type="paasword" name="paasword" onChange={ this.savePaasword } /> */}
            {/* 解决方案：给onChange绑定同一个事件，在这个事件中给整个表单的输入标签做状态变更，传一个参数，用来区别当前是哪个输入标签
            但是会带来一个问题：onChange={this.事件名}是将当前这个事件作为onChange的回调，而onChange={this.事件名(参数)}是将this.事件名(参数)的返回值作为onChange的回调
            所以事件里面就要return一个函数，交给onChange作为回调
          */}
            用户名：<input type="text" name="username" onChange={ this.saveFormData('username') } />
            密码：<input type="paasword" name="paasword" onChange={ this.saveFormData('password') } />
            <button>登录</button>
          </form>
        )
      }
    }
    ReactDOM.render(<Demo />, document.getElementById('test'))
  </script>
</body>
</html>